using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using OrdersManager.Module;
using OrdersManager.Module.Constants;
using OrdersManager.Module.Services;

namespace OrdersManager.Module.Tests.Mocks
{
	public class MockOrderWorkflowManager : IOrderWorkflowManager
	{
		private Dictionary<Guid, OrderStatus> workflow = new Dictionary<Guid, OrderStatus>();

		public OrderStatus GetOrderState(Guid orderId)
		{
			return workflow[orderId];
		}

		public Guid CreateOrderWorkflow(Guid orderId)
		{
			workflow.Add(orderId, OrderStatus.Initial);

            return Guid.Empty;
		}

		public void NotifyOrderCreated(Guid orderId)
		{
			if (!workflow.ContainsKey(orderId))
				CreateOrderWorkflow(orderId);

			if (!GetOrderPossibleStates(orderId).Contains(OrderStatus.Opened))
				throw new InvalidOperationException();
			workflow[orderId] = OrderStatus.Opened;
		}

		public void NotifyOrderProcessed(Guid orderId)
		{
			if (!GetOrderPossibleStates(orderId).Contains(OrderStatus.Processed))
				throw new InvalidOperationException();
			workflow[orderId] = OrderStatus.Processed;
		}

		public void NotifyOrderUpdated(Guid orderId)
		{
			if (!GetOrderPossibleStates(orderId).Contains(OrderStatus.Opened)
			    || GetOrderState(orderId) == OrderStatus.Initial)
				throw new InvalidOperationException();
			workflow[orderId] = OrderStatus.Opened;
		}

		public void NotifyOrderShipped(Guid orderId)
		{
			if (!GetOrderPossibleStates(orderId).Contains(OrderStatus.Shipped))
				throw new InvalidOperationException();
			workflow[orderId] = OrderStatus.Shipped;
		}

		public void NotifyOrderCancelled(Guid orderId)
		{
			if (!GetOrderPossibleStates(orderId).Contains(OrderStatus.Cancelled))
				throw new InvalidOperationException();
			workflow[orderId] = OrderStatus.Cancelled;
		}

		public ReadOnlyCollection<Guid> GetOrdersByState(OrderStatus stateMode)
		{
			List<Guid> orders = new List<Guid>();
			foreach (KeyValuePair<Guid, OrderStatus> kvp in workflow)
			{
				if (kvp.Value == stateMode)
					orders.Add(kvp.Key);
			}
			return orders.AsReadOnly();
		}

		public ReadOnlyCollection<OrderStatus> GetOrderPossibleStates(Guid orderId)
		{
			List<OrderStatus> states = new List<OrderStatus>();

			if (!workflow.ContainsKey(orderId))
				states.Add(OrderStatus.Initial);
			else
				switch (GetOrderState(orderId))
				{
					case OrderStatus.Initial:
						states.Add(OrderStatus.Opened);
						break;
					case OrderStatus.Opened:
						states.Add(OrderStatus.Opened);
						states.Add(OrderStatus.Processed);
						break;
					case OrderStatus.Processed:
						states.Add(OrderStatus.Opened);
						states.Add(OrderStatus.Shipped);
						states.Add(OrderStatus.Cancelled);
						break;
					case OrderStatus.Shipped:
						break;
					case OrderStatus.Cancelled:
						break;
				}

			return states.AsReadOnly();
		}

        #region IDisposable Members

        public void Dispose()
        {
        }

        #endregion

        public bool InstanceIsWaiting(Guid instanceId)
        {
            return false;
        }

    }
}